﻿/***
 * 
 *    Title: "ZGUIFW"UI框架项目
 *           主题： UI管理器      
 *    Description: 
 *           功能： 是整个UI框架的核心,用户通过脚本,来实现框架绝大多数的功能
 *    Date: 2018
 *    Version: 0.1版本
 */
using System.Collections;
using System.Collections.Generic;
using UnityEditorInternal;
using UnityEngine;

namespace ZGUIFW
{
    public class UIManager : MonoBehaviour
    {
        //单例模式
        private static UIManager _instance = null;
        //UI窗体预设路径 (参数1: 窗体预设名称, 参数2:  表示窗体预设路径
        private Dictionary<string, string> _dictionaryPaths;
        //缓存所有的UI窗体
        private Dictionary<string, BaseUIForm> _dicAllUiForms;
        //当前显示的UI窗体
        private Dictionary<string, BaseUIForm> _dicCurrentShowForms;
        //定义栈结构,用来保存  具备"反向切换"的 窗口的集合
        private Stack<BaseUIForm> _stackCurrentUIForms;
        //UI根节点
        private Transform _traCanvasTransform = null;
        //全名屏幕显示的节点
        private Transform _traNormal = null;
        //固定显示的节点
        private Transform _traFixed = null;
        //弹出节点
        private Transform _traPopUI = null;
        //UI管理脚本的节点
        private Transform _traUIScripts = null;

        public static UIManager GetInstance()
        {
            return _instance ?? (_instance = new GameObject("_Instance").AddComponent<UIManager>());
        }


        //
        void Awake()
        {
            //字段初始化
            _dicAllUiForms = new Dictionary<string, BaseUIForm>();
            _dicCurrentShowForms = new Dictionary<string, BaseUIForm>();
            _dictionaryPaths = new Dictionary<string, string>();
            _stackCurrentUIForms = new Stack<BaseUIForm>();

            //初始化加载 canvas prefab
            InitRootCanvasLoading();
            //得到根节点 全屏节点 固定节点 弹出节点
            _traCanvasTransform = GameObject.FindGameObjectWithTag(SystemDefine.SYS_TAG_CANVAS).transform;
            _traNormal = UnityHelper.FindTheChildNode(_traCanvasTransform.gameObject, SystemDefine.SYS_CANVAS_NORMAL);
            _traFixed = UnityHelper.FindTheChildNode(_traCanvasTransform.gameObject, SystemDefine.SYS_CANVAS_FIXED);
            _traPopUI = UnityHelper.FindTheChildNode(_traCanvasTransform.gameObject, SystemDefine.SYS_CANVAS_POPUP);
            _traUIScripts = UnityHelper.FindTheChildNode(_traCanvasTransform.gameObject, SystemDefine.SYS_CANVAS_SCRIPTMGR);

            //把本脚本作为 "根UI窗体"的子节点
            gameObject.transform.SetParent(_traUIScripts, false);
            //"根UI窗体" 在场景转换的时候,不允许销毁
            DontDestroyOnLoad(_traCanvasTransform);
            // 初始化"根UI窗体预设" 路径数据
            if (_dictionaryPaths != null)
            {
				InitUIFormsPath();
            }
        }

        //初始化加载(根UIcanvas)
        private void InitRootCanvasLoading()
        {
            ResourcesMgr.GetInstance().LoadAsset(SystemDefine.SYS_PATH_CANVAS, false);
        }

        /// <summary>
        /// 显示(打开)UI窗体
        /// 功能:
        /// 1.加载与判断指定的UI窗体的名称, 加载到All ui 缓存集合中
        /// 2.根据不同的UI窗体的显示模式, 分别作不同的加载处理
        /// </summary>
        /// <param name="uiFormName"></param>
        public void ShowUIForms(string uiFormName)
        {
            //参数的检查
            if (string.IsNullOrEmpty(uiFormName)) return;
            var baseUiForm = LoadFormsToAllUIFormsCache(uiFormName);
            if (baseUiForm == null) return;
            //是否清空栈
            if (baseUiForm.CurrentType.IsClearStack)
                ClearStack();
            // 根据不同的UI窗体的显示模式,分别做不同的加载处理
            switch (baseUiForm.CurrentType.UiFormShowMode)
            {
                //普通的显示模式
                case UIFormShowMode.Normal:
                    LoadUIToCurrentCache(uiFormName);
                    break;
                //反向切换
                case UIFormShowMode.ReverseChange:
					PushUIFormToStack(uiFormName);
                    break;
                //隐藏其他
                case UIFormShowMode.HideOther:
                    EnterUIFormsAndHideOther(uiFormName);
                    break;
            }
        }

        public void CloseUIForms(string uiFormName)
        {
            BaseUIForm baseUiForm;
            //参数检查
            if (string.IsNullOrEmpty(uiFormName)) return;
			_dicAllUiForms.TryGetValue(uiFormName, out baseUiForm);
            if (baseUiForm == null) return;

            switch (baseUiForm.CurrentType.UiFormShowMode)
            {
                case UIFormShowMode.Normal:
                    //普通窗体的关闭
                    ExitUIForms(uiFormName);
                    break;
                case UIFormShowMode.ReverseChange:
                    //反向切换窗体的关闭
                    PopUIForms(uiFormName);
                    break;
                case UIFormShowMode.HideOther:
                    //隐藏其他窗体的关闭
                    ExitUIFormAndDisplayOther(uiFormName);
                    break;
            }


        }
        private BaseUIForm LoadFormsToAllUIFormsCache(string uiFormName)
        {
            BaseUIForm baseUiForm;
            _dicAllUiForms.TryGetValue(uiFormName, out baseUiForm);
            if (baseUiForm == null)
            {
                baseUiForm = LoadUIForm(uiFormName);
            }
            return baseUiForm;
        }
        /// <summary>
        /// 加载自定的UI窗体
        /// 功能:
        /// 1.根据"UI窗体名称", 加载预设克隆体
        /// 2.加载到哪个节点下面 
        /// 3.隐藏刚创建的UI Prefab
        /// 4.把克隆体加入到 "所有UI窗体"集合中.
        /// </summary>
        /// <param name="uiFormName"></param>
        private BaseUIForm LoadUIForm(string uiFormName)
        {
            string path;  //UI窗体路径
            GameObject goCloneUiPrefab = null; //创建的UI克隆预设
            BaseUIForm baseUiForm = null;  //窗体基类


            //1.根据"UI窗体名称", 加载预设克隆体
            _dictionaryPaths.TryGetValue(uiFormName, out path);
            if (!string.IsNullOrEmpty(path))
            {
                goCloneUiPrefab = ResourcesMgr.GetInstance().LoadAsset(path, false);
            }
            // 2.加载到哪个节点下面 
            if (_traCanvasTransform != null && goCloneUiPrefab != null)
            {
                baseUiForm = goCloneUiPrefab.GetComponent<BaseUIForm>();
                if (baseUiForm == null)
                {
                    Debug.LogError("Error  can't get BaseUIForm script :" + uiFormName);
                    return null;
                }
                switch (baseUiForm.CurrentType.UiFormType)
                {
                    case UIFormType.Normal:
                        goCloneUiPrefab.transform.SetParent(_traNormal);
                        break;
                    case UIFormType.Fixed:
                        goCloneUiPrefab.transform.SetParent(_traFixed);
                        break;
                    case UIFormType.PopUP:
                        goCloneUiPrefab.transform.SetParent(_traPopUI);
                        break;
                }
                // 3.隐藏刚创建的UI Prefab
                goCloneUiPrefab.SetActive(false);
                // 4.把克隆体加入到 "所有UI窗体"集合中.
                _dicAllUiForms.Add(uiFormName, baseUiForm);
            }
            else
            {
                Debug.LogError("_traCanvasTransform == null || goCloneUiPrefab == null:" + uiFormName);
            }

            return baseUiForm;
        }

        /// <summary>
        /// 把当前窗体加载到 "当前正在显示窗体"集合中
        /// </summary>
        private void LoadUIToCurrentCache(string uiFormName)
        {
            BaseUIForm baseUiForm;      //UI窗体的基类
                                           //如果 "正在显示"的集合中, 存在现在要保存的窗体 则返回

            _dicCurrentShowForms.TryGetValue(uiFormName, out baseUiForm);
            if (baseUiForm != null) return;
            _dicAllUiForms.TryGetValue(uiFormName, out baseUiForm);
            if (baseUiForm == null)
            {
                Debug.LogError("Get BaseUIForm null :" + uiFormName);
                return;
            }
            baseUiForm.Display();
            //baseUiForm.Reset();
            _dicCurrentShowForms.Add(uiFormName, baseUiForm);
        }

        /// <summary>
        /// UI窗体入栈
        /// </summary>
        private void PushUIFormToStack(string uiFormName)
        {
            BaseUIForm uiForm;
            if (_stackCurrentUIForms.Count > 0)
            {
                _stackCurrentUIForms.Peek().Freeze();
            }
            // 思考: 为什么不是在_dicCurrentShowForms里找   参考ShowUIForms 方法
            _dicAllUiForms.TryGetValue(uiFormName, out uiForm);

            if (uiForm == null)
            {
                Debug.LogError("_dicAllUiForms find form name error :" + uiFormName);
                return;
            }
            uiForm.Display();
            _stackCurrentUIForms.Push(uiForm);
        }
        /// <summary>
        /// 退出指定窗体(普通窗体)
        /// </summary>
        /// <param name="uiFormName"></param>

        private void ExitUIForms(string uiFormName)
        {
            BaseUIForm baseUiForm;
            _dicCurrentShowForms.TryGetValue(uiFormName, out baseUiForm);
            if (baseUiForm == null) return;
            baseUiForm.Hiding();
            _dicCurrentShowForms.Remove(uiFormName);
        }
        /// <summary>
        /// 退出反向切换窗体
        /// </summary>
        /// <param name="uiFormName"></param>
        private void PopUIForms(string uiFormName)
        {
            //XXX 有必要重构.
            if (_stackCurrentUIForms.Count > 1)
            {
                //出栈处理
                BaseUIForm top = _stackCurrentUIForms.Pop();
                top.Hiding();
                BaseUIForm next = _stackCurrentUIForms.Peek();
                next.ReDisplay();
            }
            else if (_stackCurrentUIForms.Count == 1)
            {
                BaseUIForm top = _stackCurrentUIForms.Pop();
                top.Hiding();
            }
        }
        private void ExitUIFormAndDisplayOther(string uiFormName)
        {
            if (string.IsNullOrEmpty(uiFormName)) return;
            BaseUIForm baseUIForm;

            _dicCurrentShowForms.TryGetValue(uiFormName, out baseUIForm);
            if (baseUIForm == null) return;
            baseUIForm.Hiding();
            _dicCurrentShowForms.Remove(uiFormName);

            foreach(var baseUI in _dicCurrentShowForms)
            {
                baseUI.Value.ReDisplay();
            }
            foreach(var stackUI in _stackCurrentUIForms)
            {
                stackUI.ReDisplay();    
            }
        }

        /// <summary>
        /// 隐藏其他
        /// </summary>
        private void EnterUIFormsAndHideOther(string uiFormName)
        {
            BaseUIForm baseUiForm;
            BaseUIForm baseUIFormFromAll;

            if (string.IsNullOrEmpty(uiFormName)) return;
            _dicCurrentShowForms.TryGetValue(uiFormName, out baseUiForm);
            if (baseUiForm != null) return;

            foreach (var v in _dicCurrentShowForms)
            {
                v.Value.Hiding();
            }
            foreach (var v in _stackCurrentUIForms)
            {
                v.Hiding();
            }
            _dicAllUiForms.TryGetValue(uiFormName, out baseUIFormFromAll);
            if (baseUIFormFromAll == null)
            {
                Debug.LogError("Can't find the name:" + uiFormName);
                return;
            }
            _dicCurrentShowForms.Add(uiFormName, baseUIFormFromAll);
            baseUIFormFromAll.Display();
            //baseUIFormFromAll.Reset();
        }
        /// <summary>
        /// Clears the stack.
        /// </summary>
        private void ClearStack()
        {
            if (_stackCurrentUIForms == null || _stackCurrentUIForms.Count == 0) return;
            _stackCurrentUIForms.Clear();
        }

        /// <summary>
        /// Inits the UI Forms path.
        /// </summary>
		private void InitUIFormsPath()
		{
			IConfigMgr configMgr = new ConfigMgrByJson(SystemDefine.SYS_PATH_UIFORMS_CONFIG);
			if (configMgr == null)
			{
				return;
			}
			_dictionaryPaths = configMgr.AppSetting;
		}
        #region 测试工具

        public int ShowAllUIFormsCount()
        {
            if (_dicAllUiForms == null) return -1;
            return _dicAllUiForms.Count;
        }

        public int ShowCurrentUIFormsCount()
        {
            if (_dicCurrentShowForms == null) return -1;
            return _dicCurrentShowForms.Count;
        }

        public int ShowCurrentStackUIFormsCount()
        {
            if (_stackCurrentUIForms == null) return -1;
            return _stackCurrentUIForms.Count;
        }

        #endregion
    }

}

